package com.zeny.express.framework.mq.ibmmq;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ibm.mq.MQC;
import com.ibm.mq.MQException;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
import com.zeny.express.framework.mq.AbstractMqPool;
import com.zeny.express.framework.mq.MqCallback;
import com.zeny.express.framework.shared.exception.ApplicationException;

public class IBMMqTemplate {
	protected final static Logger LOGGER = LoggerFactory
			.getLogger(IBMMqTemplate.class);

	@SuppressWarnings("deprecation")
	private int queueOpenOptions = MQC.MQOO_INPUT_AS_Q_DEF | MQC.MQOO_OUTPUT;
	
	@SuppressWarnings("deprecation")
	public <T> T execute(AbstractMqPool<?> _mqPool, MqCallback<T, MQQueue> action) {
		
		IBMMqPool mqPool = (IBMMqPool)_mqPool;
		
		MQQueue queue = null;
		boolean success = false;

		try {
			queue = (MQQueue)mqPool.getResource();
			
			T result = action.doInMq(queue);

			success = true;

			return result;
		} catch (MQException mqe) {
			if ((mqe.getCompCode() == MQException.MQCC_FAILED)
					&& (mqe.getReason() == MQException.MQRC_NO_MSG_AVAILABLE)) {
				LOGGER.info("{} {} NO_MSG_AVAILABLE",
						mqPool.getQueueManagerName(), mqPool.getQueueName());
				return null;
			}

			LOGGER.error(mqe.getMessage(), mqe);
			throw new ApplicationException(ApplicationException.UNKNOWN, null);
		} catch (Exception mqe) {
			LOGGER.error(mqe.getMessage(), mqe);
			throw new ApplicationException(ApplicationException.UNKNOWN, null);
		} finally {
			if (queue != null) {
				try {
					MQQueueManager queueManager = queue.getConnectionReference();

					if (success) {
						queueManager.commit();
						
						mqPool.returnResource(queue);
					} else {
						queueManager.backout();
						
						mqPool.returnBrokenResource(queue);
					}
				} catch (MQException mqe) {
					mqPool.returnBrokenResource(queue);
					
					LOGGER.error(mqe.getMessage(), mqe);
					throw new ApplicationException(
							ApplicationException.UNKNOWN, null);
				}
			}
		}

	}
}
